#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""符号表和类型系统

简化版符号表，专注于：
1. 外部stub文件处理
2. 导入的外部模块管理
3. 基础类型定义
4. 类型解析工具
"""

from typing import Dict, List, Optional
from .symbol_meta import Symbol, TypeInfo, TypeKind, SymbolKind
from .symbol_registry import SymbolRegistry, get_global_registry
from .type_system import parse_type


class SymbolTable:
    """符号表 - 处理外部stub和导入模块"""

    def __init__(self):
        # 模块本地的符号注册表
        self.symbol_registry: SymbolRegistry = SymbolRegistry()

        # 导入的类型映射（新增）
        self._imported_types: Dict[str, Symbol] = {}

    def _lookup_function(
        self,
        name: str,
        args_types: Optional[List[TypeInfo]] = None,
        registry: Optional[SymbolRegistry] = None,
    ) -> Optional[Symbol]:
        """查找内建函数符号

        使用builtin模块提供的便利查询函数，避免直接访问内部注册表

        Args:
            name: 函数名
            args_types: 参数类型列表，用于重载函数匹配

        Returns:
            Optional[Symbol]: 内建函数符号，如果不存在则返回None
        """

        # 使用提供的 registry 或者本地的 symbol_registry 查找函数符号
        if not registry:
            return None

        signature = registry.find_best_match_with_typeinfo(name, args_types)
        if not signature:
            return None

        # 解析返回类型
        return_type = None
        if signature.return_type:
            # 检查是否需要进行模板参数替换
            if signature.template_params and args_types:
                return_type = self._substitute_template_params(
                    signature.return_type,
                    signature.template_params,
                    args_types,
                    signature,
                )
            else:
                return_type = parse_type(signature.return_type)

        # 创建函数类型信息
        function_type = TypeInfo(
            kind=TypeKind.FUNCTION,
            name=name,
            args=args_types or [],
            return_type=return_type,
            module="builtins",
        )

        # 创建符号并添加匹配的签名
        symbol = Symbol(
            name=name,
            kind=SymbolKind.FUNCTION,
            type_info=function_type,
            module="builtins",
        )

        # 添加匹配的签名到符号中
        symbol.add_signature(signature)

        return symbol

    def register_imported_type(self, type_name: str, symbol: Symbol) -> None:
        """注册从 stub 导入的类型

        Args:
            type_name: 类型名称
            symbol: 类型符号
        """
        self._imported_types[type_name] = symbol
        self.symbol_registry.register_type_symbol(symbol)

    def get_type_config(self, type_name: str) -> Optional[Dict]:
        """获取类型配置"""
        return self.symbol_registry.get_type_config(type_name)

    def register_imported_type_config(self, type_name: str, config: Dict) -> None:
        """注册从 stub 导入的类型配置

        Args:
            type_name: 类型名称
            config: 类型配置字典
        """
        self.symbol_registry.register_type_config(type_name, config)

    def _lookup_type_symbol(self, type_name: str) -> Optional[Symbol]:
        """查找类型符号（模块本地 + 全局）

        Args:
            type_name: 类型名称

        Returns:
            类型符号，如果不存在则返回 None
        """
        # 1. 查找模块本地类型符号
        local_type = self.symbol_registry.lookup_type_symbol(type_name)
        if local_type:
            return local_type

        # 2. 查找全局内置类型符号
        return self._lookup_global_type_symbol(type_name)

    def _lookup_global_type_symbol(self, type_name: str) -> Optional[Symbol]:
        """查找全局内置类型符号

        Args:
            type_name: 类型名称

        Returns:
            全局类型符号，如果不存在则返回 None
        """
        # 直接从全局符号表查找，避免重复创建符号
        from .symbol_registry import get_global_registry

        global_registry = get_global_registry()
        return global_registry.lookup_type_symbol(type_name)

    def _substitute_template_params(
        self,
        return_type_str: str,
        template_params: List[str],
        args_types: List[TypeInfo],
        signature=None,
    ) -> Optional[TypeInfo]:
        """替换函数签名中的模板参数

        注意：args_types 应该包含所有参数的类型，包括方法调用中的 self 参数类型。
        对于方法调用如 my_list.pop()，args_types 应该是 [list[int]]，
        这样就能从 self 参数类型 list[int] 中提取出 T=int 的映射。

        Args:
            return_type_str: 返回类型字符串，如 "list[tuple[int, T]]"
            template_params: 模板参数列表，如 ["T"]
            args_types: 实际参数类型列表（包含 self 参数类型）
            signature: 函数签名对象，包含模板参数位置映射信息

        Returns:
            替换后的TypeInfo对象
        """
        from .type_system import decode_generic_type_str

        type_mapping: Dict[str, TypeInfo] = {}
        if (
            signature
            and hasattr(signature, "template_param_mapping")
            and signature.template_param_mapping
        ):
            type_mapping = self._build_type_mapping_with_position(
                signature.template_param_mapping, args_types
            )

        # 检查是否所有模板参数都有映射
        missing_params = [
            param for param in template_params if param not in type_mapping
        ]
        if missing_params:
            # 有未映射的模板参数，返回UNKNOWN类型
            return TypeInfo.unknown()

        base_name, type_str_args = decode_generic_type_str(return_type_str)
        result_type = self._substitute_type_info_params(
            base_name, type_str_args, type_mapping
        )

        return result_type

    def _substitute_type_info_params(
        self,
        base_name: str,
        type_str_args: list[str],
        type_mapping: Dict[str, TypeInfo],
    ) -> TypeInfo:
        """递归替换TypeInfo中的模板参数

        Args:
            type_info: 要处理的TypeInfo对象
            type_mapping: 模板参数到实际类型的映射

        Returns:
            替换后的TypeInfo对象
        """
        from .type_system import (
            parse_type,
            decode_generic_type_str,
            is_generic_type,
        )

        # 如果没有泛型参数
        if not type_str_args:
            # 检查 base_name 是否是模板参数（如 T）
            if base_name in type_mapping:
                return type_mapping[base_name]
            # 否则正常解析类型
            return parse_type(base_name) or TypeInfo.unknown()

        new_args = []
        for arg in type_str_args:
            if not is_generic_type(arg):
                if arg in type_mapping:
                    new_args.append(type_mapping[arg])
                else:
                    new_args.append(parse_type(arg))
            else:
                arg_base_name, arg_strs = decode_generic_type_str(arg)
                new_args.append(
                    self._substitute_type_info_params(
                        arg_base_name, arg_strs, type_mapping
                    )
                )

        return TypeInfo(
            kind=TypeKind.GENERIC,
            name=base_name,
            module="",
            args=new_args,
            attributes={},
            methods={},
            base_types=[],
            return_type=None,
        )

    def _build_type_mapping_with_position(
        self,
        template_param_mapping: Dict[str, Dict[str, int]],
        args_types: List[TypeInfo],
    ) -> Dict[str, TypeInfo]:
        """根据模板参数位置映射构建类型映射

        Args:
            template_param_mapping: 模板参数位置映射，格式：
                {模板参数名: {'param_index': 参数索引, 'type_arg_index': 类型参数索引}}
            args_types: 实际参数类型列表

        Returns:
            Dict[str, TypeInfo]: 模板参数到实际类型的映射
        """
        type_mapping = {}

        for template_param, position_info in template_param_mapping.items():
            param_index = position_info["param_index"]
            type_arg_index = position_info["type_arg_index"]

            # 检查参数索引是否有效
            if param_index >= len(args_types):
                continue

            arg_type = args_types[param_index]

            if type_arg_index == -1:
                # 直接参数类型（如参数类型就是 T）
                type_mapping[template_param] = arg_type
            else:
                # 泛型参数类型（如从 list[T] 中提取 T）
                if (
                    hasattr(arg_type, "args")
                    and arg_type.args
                    and type_arg_index < len(arg_type.args)
                ):
                    actual_type = arg_type.args[type_arg_index]
                    type_mapping[template_param] = actual_type

        return type_mapping

    def _lookup_symbol(
        self,
        name: str,
        args_types: Optional[List[TypeInfo]] = None,
        registry: Optional[SymbolRegistry] = None,
        symbol_kinds: Optional[List[SymbolKind]] = None,
    ) -> Optional[Symbol]:
        """查找符号（函数 + 类型）

        Args:
            name: 符号名称
            args_types: 参数类型列表，用于重载函数匹配或模板类型匹配
            registry: 符号注册表
            symbol_kinds: 要查找的符号类型列表，如 [SymbolKind.FUNCTION, SymbolKind.CLASS]
                         如果为 None，则先查找函数，再查找类型

        Returns:
            匹配的符号，如果找不到则返回None
        """
        # 如果未指定 symbol_kinds，先查找函数，再查找类型
        if symbol_kinds is None:
            # 先查找函数
            symbol = self._lookup_function(name, args_types, registry)
            if symbol:
                return symbol
            # 再查找类型
            return self._lookup_type_with_args(name, args_types, registry)

        # 如果指定了 symbol_kinds，按优先级查找
        # 先查找函数
        if SymbolKind.FUNCTION in symbol_kinds or SymbolKind.METHOD in symbol_kinds:
            symbol = self._lookup_function(name, args_types, registry)
            if symbol:
                return symbol

        # 再查找类型
        if SymbolKind.CLASS in symbol_kinds or SymbolKind.VARIABLE in symbol_kinds:
            return self._lookup_type_with_args(name, args_types, registry)

        return None

    def _lookup_type_with_args(
        self,
        name: str,
        args_types: Optional[List[TypeInfo]] = None,
        registry: Optional[SymbolRegistry] = None,
    ) -> Optional[Symbol]:
        """查找类型符号，支持泛型参数匹配"""

        # 直接使用 registry 的泛型支持
        if registry:
            return registry.lookup_type_symbol(name, args_types)
        else:
            global_registry = get_global_registry()
            return global_registry.lookup_type_symbol(name, args_types)

    def lookup_symbol(
        self,
        name: str,
        symbol_kinds: Optional[List[SymbolKind]] = None,
        *,
        template_args: Optional[List[TypeInfo]] = None,  # 模板参数
        func_args: Optional[List[TypeInfo]] = None,  # 函数参数
    ) -> Optional[Symbol]:
        """查找符号（新接口：支持模板参数和函数参数分离）

        Args:
            name: 符号名称
            symbol_kinds: 要查找的符号类型列表，如 [SymbolKind.FUNCTION, SymbolKind.CLASS]
                         如果为 None，则先查找函数，再查找类型
            template_args: 模板参数（用于类型查询），如 list[int] 传入 [TypeInfo(name="int")]
            func_args: 函数参数（用于函数查询），如 max(1, 2) 传入 [TypeInfo(name="int"), TypeInfo(name="int")]

        Returns:
            匹配的符号，如果找不到则返回None

        示例:
            # 查询类型：list[int]
            symbol_table.lookup_symbol("list", template_args=[TypeInfo(name="int")])

            # 查询函数：max(int, int)
            symbol_table.lookup_symbol("max", func_args=[TypeInfo(name="int"), TypeInfo(name="int")])

            # 查询模板函数：cast[int](Any)
            symbol_table.lookup_symbol("cast",
                                      template_args=[TypeInfo(name="int")],
                                      func_args=[TypeInfo(name="Any")])
        """
        # 新接口逻辑：分别查找
        # 决定查找哪种类型的符号
        search_funcs = (
            symbol_kinds is None
            or SymbolKind.FUNCTION in symbol_kinds
            or SymbolKind.METHOD in symbol_kinds
        )
        search_types = (
            symbol_kinds is None
            or SymbolKind.CLASS in symbol_kinds
            or SymbolKind.VARIABLE in symbol_kinds
        )

        # 如果同时指定了 template_args 和 func_args，这是模板函数查询
        if template_args is not None and func_args is not None:
            # TODO: 实现模板函数查询（需要先查找函数符号，再根据 template_args 实例化）
            # 目前简化处理：只使用 func_args 查找函数
            if search_funcs:
                return self._lookup_function(name, func_args, self.symbol_registry)
            return None

        # 只有 template_args：类型查询
        if template_args is not None:
            if search_types:
                return self._lookup_type_with_args(
                    name, template_args, self.symbol_registry
                )
            return None

        # 只有 func_args：函数查询
        if func_args is not None:
            if search_funcs:
                return self._lookup_function(name, func_args, self.symbol_registry)
            return None

        # 都没有指定：查找无参数符号
        return self._lookup_symbol(name, None, self.symbol_registry, symbol_kinds)

    def lookup_global_symbol(
        self,
        name: str,
        symbol_kinds: Optional[List[SymbolKind]] = None,
        *,
        template_args: Optional[List[TypeInfo]] = None,  # 模板参数
        func_args: Optional[List[TypeInfo]] = None,  # 函数参数
    ) -> Optional[Symbol]:
        """查找全局符号（新接口：支持模板参数和函数参数分离）

        Args:
            name: 符号名称
            args_types: [已废弃] 参数类型列表
            symbol_kinds: 要查找的符号类型列表
            template_args: 模板参数（用于类型查询）
            func_args: 函数参数（用于函数查询）

        Returns:
            匹配的符号，如果找不到则返回None
        """
        # 新接口逻辑（复制from lookup_symbol）
        search_funcs = (
            symbol_kinds is None
            or SymbolKind.FUNCTION in symbol_kinds
            or SymbolKind.METHOD in symbol_kinds
        )
        search_types = (
            symbol_kinds is None
            or SymbolKind.CLASS in symbol_kinds
            or SymbolKind.VARIABLE in symbol_kinds
        )

        registry = get_global_registry()

        if template_args is not None and func_args is not None:
            if search_funcs:
                return self._lookup_function(name, func_args, registry)
            return None

        if template_args is not None:
            if search_types:
                return self._lookup_type_with_args(name, template_args, registry)
            return None

        if func_args is not None:
            if search_funcs:
                return self._lookup_function(name, func_args, registry)
            return None

        return self._lookup_symbol(name, None, registry, symbol_kinds)

    def lookup_method_symbol(
        self,
        owner_type: "str | TypeInfo",  # 支持 str 或 TypeInfo
        method_name: str,
        args_types: Optional[List] = None,
    ) -> Optional[Symbol]:
        """查找类方法符号（使用类作用域）

        Args:
            owner_type: 类名（str）或类型信息（TypeInfo）
            method_name: 方法名
            args_types: 方法参数类型列表（不包含 self）

        Returns:
            方法符号，如果不存在则返回 None
        """
        # 如果传入的是 TypeInfo，转换成字符串
        if isinstance(owner_type, TypeInfo):
            from .symbol_meta import build_type_signature

            class_name = build_type_signature(owner_type)
        else:
            class_name = owner_type

        # 先查找本地注册的方法
        if hasattr(self, "symbol_registry") and self.symbol_registry:
            symbol = self.symbol_registry.lookup_instance_method(
                class_name, method_name, args_types
            )
            if symbol:
                return symbol

        # 查找全局注册的方法
        return get_global_registry().lookup_instance_method(
            class_name, method_name, args_types
        )

    def get_symbol(self, name: str) -> Optional[Symbol]:
        """获取符号（直接从注册表获取，不进行作用域查找）

        Args:
            name: 符号名称

        Returns:
            符号对象，如果不存在则返回 None
        """
        return self.symbol_registry.get_symbol(name)

    def register_function_symbol(self, symbol: Symbol) -> None:
        """注册函数符号

        Args:
            symbol: 函数符号
        """
        self.symbol_registry.register_function_symbol(symbol)

    def register_signature(self, signature) -> None:
        """注册函数签名

        Args:
            signature: 函数签名对象
        """
        self.symbol_registry.register_signature(signature)

    def lookup_function_in_registry(
        self, name: str, args_types: Optional[List[TypeInfo]] = None
    ) -> Optional[Symbol]:
        """在本模块的符号注册表中查找函数符号

        注意：这个方法用于查找本模块注册表中的函数（包括从其他模块导入的函数）

        Args:
            name: 函数名（可以包含模块前缀，如 "module.function"）
            args_types: 参数类型列表

        Returns:
            函数符号，如果不存在则返回 None
        """
        return self.symbol_registry.lookup_global_function(name, args_types)

    def lookup_global_function(
        self, name: str, args_types: Optional[List[TypeInfo]] = None
    ) -> Optional[Symbol]:
        """在全局符号注册表中查找函数符号

        注意：这个方法应该只在特殊情况下使用（如查找内置函数）
        一般情况应该通过 IR 节点的 lookup_symbol 方法进行符号查找

        Args:
            name: 函数名
            args_types: 参数类型列表

        Returns:
            函数符号，如果不存在则返回 None
        """
        registry = get_global_registry()
        return registry.lookup_global_function(name, args_types)

    def register_template_type(
        self,
        name: str,
        template_params: List[str],
        cpp_template: str,
        is_variadic: bool = False,
    ) -> None:
        """注册模板类型

        Args:
            name: 类型名称
            template_params: 模板参数列表
            cpp_template: C++ 模板字符串
            is_variadic: 是否是可变参数模板
        """
        self.symbol_registry.register_template_type(
            name=name,
            template_params=template_params,
            cpp_template=cpp_template,
            is_variadic=is_variadic,
        )
